home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS09.ADF / MicroEMACS / random.c < prev    next >
C/C++ Source or Header  |  1986-05-22  |  14KB  |  483 lines

  1. /*
  2.  * This file contains the command processing functions for a number of random
  3.  * commands. There is no functional grouping here, for sure.
  4.  */
  5.  
  6. #include        <stdio.h>
  7. #include        "ed.h"
  8.  
  9. int     tabsize;                        /* Tab size (0: use real tabs)  */
  10.  
  11. /*
  12.  * Toggle word wrap.
  13.  */
  14. togglewordwrap(f, n)
  15. {
  16.     if( wordwrap) {
  17.     wordwrap = FALSE;
  18.     mlwrite( "Word wrap off");
  19.     } else {
  20.     wordwrap = TRUE;
  21.     mlwrite( "Word wrap on");
  22.     }
  23.         return(TRUE);
  24. }
  25.  
  26. /*
  27.  * Toggle autoindent
  28.  */
  29. toggleautoindent(f, n)
  30. {
  31.     if( autoindent ) 
  32.     {
  33.     autoindent = FALSE;
  34.     mlwrite( "Autoindentation is off");
  35.         } 
  36.     else 
  37.     {
  38.     autoindent = TRUE;
  39.     mlwrite( "Autoindentation is on");
  40.         }
  41.     return(TRUE);
  42. }
  43.  
  44. /*
  45.  * Set fill column (Right Margin) and Left margin 
  46.  */
  47. setfillcol(f, n)
  48. {
  49. register int    c;
  50. register char    *prompt;
  51.  
  52. if ( f )
  53.     prompt = "Right Margin: %d";
  54. else
  55.     prompt = "Left Margin : %d";
  56.     
  57. n = 0;
  58. mlwrite( prompt, n );
  59. while ( (c=getkey()) >='0' && c<='9' )
  60.    {
  61.    n = 10*n + c - '0';
  62.    mlwrite( prompt, n );
  63.    }
  64.  
  65. if ( f )
  66.     fillcol = n;
  67. else
  68.     LeftMargin = n;
  69.     
  70. return(TRUE);
  71. }
  72.  
  73. /*
  74.  * Display the current position of the cursor, in origin 1 X-Y coordinates,
  75.  * the character that is under the cursor (in octal), and the fraction of the
  76.  * text that is before the cursor. The displayed column is not the current
  77.  * column, but the column that would be used on an infinite width display.
  78.  * Normally this is bound to "C-X =".
  79.  */
  80. showcpos(f, n)
  81. {
  82.         register LINE   *clp;
  83.         register long   nch;
  84.     register long    nbc;
  85.         register int    cbo;
  86.         register int    cac;
  87.         register int    ratio;
  88.         register short  col;
  89.  
  90.         clp = lforw(curbp->b_linep);            /* Grovel the data.     */
  91.         cbo = 0;
  92.         nch = 0;
  93.         for (;;) {
  94.                 if (clp==curwp->w_dotp && cbo==curwp->w_doto) {
  95.                         nbc = nch;
  96.                         if (cbo == llength(clp))
  97.                                 cac = '\n';
  98.                         else
  99.                                 cac = lgetc(clp, cbo);
  100.                 }
  101.                 if (cbo == llength(clp)) {
  102.                         if (clp == curbp->b_linep)
  103.                                 break;
  104.                         clp = lforw(clp);
  105.                         cbo = 0;
  106.                 } else
  107.                         ++cbo;
  108.                 ++nch;
  109.         }
  110.         col = getccol(FALSE);                   /* Get real column.     */
  111.         ratio = 0;                              /* Ratio before dot.    */
  112.         if (nch != 0)
  113.                 ratio = (100L*nbc) / nch;
  114.         mlwrite("row=%d  col=%d  CH=0x%x  .=%D  (%d%% of %D)",
  115.                 currow+1, col+1, cac, nbc, ratio, nch);
  116.         return (TRUE);
  117. }
  118.  
  119. /*
  120.  * Return current column.  Stop at first non-blank given TRUE argument.
  121.  */
  122. getccol(bflg)
  123. int bflg;
  124. {
  125. register short c, i, col;
  126.  
  127. col = 0;
  128. for (i=0; i<curwp->w_doto; ++i) 
  129.     {
  130.     c = lgetc(curwp->w_dotp, i);
  131.     if (bflg && c != ' ' && c != '\t')
  132.         break;
  133.     if (c == '\t')
  134.         col |= 0x07;
  135.     else if (c<0x20 || c==0x7F)
  136.         ++col;
  137.     ++col;
  138.         }
  139. return(col);
  140. }
  141.  
  142. /*
  143.  * Twiddle the two characters on either side of dot. If dot is at the end of
  144.  * the line twiddle the two characters before it. Return with an error if dot
  145.  * is at the beginning of line; it seems to be a bit pointless to make this
  146.  * work. This fixes up a very common typo with a single stroke. Normally bound
  147.  * to "C-T". This always works within a line, so "WFEDIT" is good enough.
  148.  */
  149. twiddle(f, n)
  150. {
  151.         register LINE   *dotp;
  152.         register int    doto;
  153.         register int    cl;
  154.         register int    cr;
  155.  
  156.         dotp = curwp->w_dotp;
  157.         doto = curwp->w_doto;
  158.         if (doto==llength(dotp) && --doto<0)
  159.                 return (FALSE);
  160.         cr = lgetc(dotp, doto);
  161.         if (--doto < 0)
  162.                 return (FALSE);
  163.         cl = lgetc(dotp, doto);
  164.         lputc(dotp, doto+0, cr);
  165.         lputc(dotp, doto+1, cl);
  166.         lchange(WFEDIT);
  167.         return (TRUE);
  168. }
  169.  
  170. /*
  171.  * Quote the next character, and insert it into the buffer. All the characters
  172.  * are taken literally, with the exception of the newline, which always has
  173.  * its line splitting meaning. The character is always read, even if it is
  174.  * inserted 0 times, for regularity. Bound to "M-Q" (for me) and "C-Q" (for
  175.  * Rich, and only on terminals that don't need XON-XOFF).
  176.  */
  177. quote(f, n)
  178. {
  179.         register int    s;
  180.         register int    c;
  181.  
  182.         c = (*term.t_getchar)();
  183.         if (n < 0)
  184.                 return (FALSE);
  185.         if (n == 0)
  186.                 return (TRUE);
  187.         if (c == '\n') {
  188.                 do {
  189.                         s = lnewline();
  190.                 } while (s==TRUE && --n);
  191.                 return (s);
  192.         }
  193.         return (linsert(n, c));
  194. }
  195.  
  196. /*
  197.  * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
  198.  * tab into file.  If given argument, n, of zero, change to true tabs.
  199.  * If n > 1, simulate tab stop every n-characters using spaces. This has to be
  200.  * done in this slightly funny way because the tab (in ASCII) has been turned
  201.  * into "C-I" (in 10 bit code) already. Bound to "C-I".
  202.  */
  203. tab(f, n)
  204. {
  205.         if (n < 0)
  206.                 return (FALSE);
  207.         if (n == 0 || n > 1) {
  208.                 tabsize = n;
  209.                 return(TRUE);
  210.         }
  211.         if (! tabsize)
  212.                 return(linsert(1, '\t'));
  213.         return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
  214. }
  215.  
  216. /*
  217.  * Open up some blank space. The basic plan is to insert a bunch of newlines,
  218.  * and then back up over them. Everything is done by the subcommand
  219.  * procerssors. They even handle the looping. Normally this is bound to "C-O".
  220.  */
  221. openline(f, n)
  222. {
  223.         register int    i;
  224.         register int    s;
  225.  
  226.         if (n < 0)
  227.                 return (FALSE);
  228.         if (n == 0)
  229.                 return (TRUE);
  230.         i = n;                                  /* Insert newlines.     */
  231.         do {
  232.                 s = lnewline();
  233.         } while (s==TRUE && --i);
  234.         if (s == TRUE)                          /* Then back up overtop */
  235.                 s = backchar(f, n);             /* of them all.         */
  236.         return (s);
  237. }
  238.  
  239. /*
  240.  * Insert a newline. Bound to "C-M". If you are at the end of the line and the
  241.  * next line is a blank line, just move into the blank line. This makes "C-O"
  242.  * and "C-X C-O" work nicely, and reduces the ammount of screen update that
  243.  * has to be done. This would not be as critical if screen update were a lot
  244.  * more efficient.
  245.  */
  246. newline(f, n)
  247. {
  248.         int nicol;
  249.         register LINE   *lp;
  250.         register int    s;
  251.  
  252.         if (n < 0)
  253.                 return (FALSE);
  254.         while (n--) {
  255.                 lp = curwp->w_dotp;
  256.                 if (llength(lp) == curwp->w_doto
  257.                 && lp != curbp->b_linep
  258.                 && llength(lforw(lp)) == 0) {
  259.                         if ((s=forwchar(FALSE, 1)) != TRUE)
  260.                                 return (s);
  261.                 } else if ((s=lnewline()) != TRUE)
  262.                         return (s);
  263.         }
  264.         return (TRUE);
  265. }
  266.  
  267. /*
  268.  * Delete blank lines around dot. What this command does depends if dot is
  269.  * sitting on a blank line. If dot is sitting on a blank line, this command
  270.  * deletes all the blank lines above and below the current line. If it is
  271.  * sitting on a non blank line then it deletes all of the blank lines after
  272.  * the line. Normally this command is bound to "C-X C-O". Any argument is
  273.  * ignored.
  274.  */
  275. deblank(f, n)
  276. {
  277.         register LINE   *lp1;
  278.         register LINE   *lp2;
  279.         register int    nld;
  280.  
  281.         lp1 = curwp->w_dotp;
  282.         while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  283.                 lp1 = lp2;
  284.         lp2 = lp1;
  285.         nld = 0;
  286.         while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  287.                 ++nld;
  288.         if (nld == 0)
  289.                 return (TRUE);
  290.         curwp->w_dotp = lforw(lp1);
  291.         curwp->w_doto = 0;
  292.         return (ldelete(nld));
  293. }
  294.  
  295. /*
  296.  * Insert a newline, then enough tabs and spaces to duplicate the indentation
  297.  * of the previous line. Assumes tabs are every eight characters. Quite simple.
  298.  * Figure out the indentation of the current line. Insert a newline by calling
  299.  * the standard routine. Insert the indentation by inserting the right number
  300.  * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
  301.  * subcomands failed. Normally bound to "C-J".
  302.  */
  303. indent(f, n)
  304. {
  305.         register int    nicol;
  306.         register int    c;
  307.         register int    i;
  308.  
  309.         if (n < 0)
  310.                 return (FALSE);
  311.         while (n--) {
  312.                 nicol = 0;
  313.                 for (i=0; i<llength(curwp->w_dotp); ++i) {
  314.                         c = lgetc(curwp->w_dotp, i);
  315.                         if (c!=' ' && c!='\t')
  316.                                 break;
  317.                         if (c == '\t')
  318.                                 nicol |= 0x07;
  319.                         ++nicol;
  320.                 }
  321.                 if ( lnewline() == FALSE )
  322.             return (FALSE);
  323.         if ( autoindent )
  324.             {
  325.             if ( ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE) ||
  326.                          ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE) )
  327.                         return (FALSE);
  328.             }
  329.         }
  330.         return (TRUE);
  331. }
  332.  
  333. /*
  334.  * Delete forward. This is real easy, because the basic delete routine does
  335.  * all of the work. Watches for negative arguments, and does the right thing.
  336.  * If any argument is present, it kills rather than deletes, to prevent loss
  337.  * of text if typed with a big argument. Normally bound to "C-D".
  338.  */
  339. forwdel(f, n)
  340. {
  341.         if (n < 0)
  342.                 return (backdel(f, -n));
  343.         if (f != FALSE) {                       /* Really a kill.       */
  344.                 if ((lastflag&CFKILL) == 0)
  345.                         kdelete();
  346.                 thisflag |= CFKILL;
  347.         }
  348.         return (ldelete(n, f));
  349. }
  350.  
  351. /*
  352.  * Delete backwards. This is quite easy too, because it's all done with other
  353.  * functions. Just move the cursor back, and delete forwards. Like delete
  354.  * forward, this actually does a kill if presented with an argument. Bound to
  355.  * both "RUBOUT" and "C-H".
  356.  */
  357. backdel(f, n)
  358. {
  359.         register int    s;
  360.  
  361.         if (n < 0)
  362.                 return (forwdel(f, -n));
  363.         if (f != FALSE) {                       /* Really a kill.       */
  364.                 if ((lastflag&CFKILL) == 0)
  365.                         kdelete();
  366.                 thisflag |= CFKILL;
  367.         }
  368.         if ((s=backchar(f, n)) == TRUE)
  369.                 s = ldelete(n, f);
  370.         return (s);
  371. }
  372.  
  373. /*
  374.  * Kill text. If called without an argument, it kills from dot to the end of
  375.  * the line, unless it is at the end of the line, when it kills the newline.
  376.  * If called with an argument of 0, it kills from the start of the line to dot.
  377.  * If called with a positive argument, it kills from dot forward over that
  378.  * number of newlines. If called with a negative argument it kills backwards
  379.  * that number of newlines. Normally bound to "C-K".
  380.  */
  381. kill(f, n)
  382. {
  383.         register int    chunk;
  384.         register LINE   *nextp;
  385.  
  386.         if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
  387.                 kdelete();                      /* last wasn't a kill.  */
  388.         thisflag |= CFKILL;
  389.         if (f == FALSE) {
  390.                 chunk = llength(curwp->w_dotp)-curwp->w_doto;
  391.                 if (chunk == 0)
  392.                         chunk = 1;
  393.         } else if (n == 0) {
  394.                 chunk = curwp->w_doto;
  395.                 curwp->w_doto = 0;
  396.         } else if (n > 0) {
  397.                 chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  398.                 nextp = lforw(curwp->w_dotp);
  399.                 while (--n) {
  400.                         if (nextp == curbp->b_linep)
  401.                                 return (FALSE);
  402.                         chunk += llength(nextp)+1;
  403.                         nextp = lforw(nextp);
  404.                 }
  405.         } else {
  406.                 mlwrite("neg kill");
  407.                 return (FALSE);
  408.         }
  409.         return (ldelete(chunk, TRUE));
  410. }
  411.  
  412. /*
  413.  * Yank text back from the kill buffer. This is really easy. All of the work
  414.  * is done by the standard insert routines. All you do is run the loop, and
  415.  * check for errors. Bound to "C-Y". The blank lines are inserted with a call
  416.  * to "newline" instead of a call to "lnewline" so that the magic stuff that
  417.  * happens when you type a carriage return also happens when a carriage return
  418.  * is yanked back from the kill buffer.
  419.  */
  420. yank(f, n)
  421. {
  422.         register int    c;
  423.         register int    i;
  424.         extern   int    kused;
  425.  
  426.         if (n < 0)
  427.                 return (FALSE);
  428.         while (n--) {
  429.                 i = 0;
  430.                 while ((c=kremove(i)) >= 0) {
  431.                         if (c == '\n') {
  432.                                 if (newline(FALSE, 1) == FALSE)
  433.                                         return (FALSE);
  434.                         } else {
  435.                                 if (linsert(1, c) == FALSE)
  436.                                         return (FALSE);
  437.                         }
  438.                         ++i;
  439.                 }
  440.         }
  441.         return (TRUE);
  442. }
  443.  
  444. /*
  445.  * Yank text back from the kill buffer and into a file. This is really easy.
  446.  * its just yank() that goes to a file
  447.  */
  448.  
  449. #define NAMELEN   30
  450. fileyank(f, n)
  451. {
  452. register long   len;
  453. register short    i;
  454. register short    c;
  455. unsigned char    filename[NAMELEN];
  456. extern     FILE    *ffp;
  457.  
  458. if (n < 0)
  459.    return (FALSE);
  460. if ( mlreply( "Yank to file: ", filename, NAMELEN) != TRUE)
  461.    return (FALSE);
  462. if ( ffwopen( filename ) == FIOERR )
  463.    return (FALSE);
  464.  
  465. len = 0L;
  466. do
  467.    {
  468.    for ( i = 0; ( i < 512 ) && ( (c=kremove(len+i)) >= 0 ); i++)
  469.     fputc( (unsigned char) c, ffp);
  470.    len += i;
  471.  
  472.    if (ferror(ffp))
  473.     {
  474.     mlwrite("Write I/O error");
  475.     i = 0;            /* abort by short circuit */
  476.     }
  477.    }
  478. while ( i == 512 );
  479.  
  480. ffclose();
  481. return (TRUE);
  482. }
  483.